using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;


namespace AOT
{
	// Mono AOT compiler detects this attribute by name and generates required wrappers for 
	// native->managed callbacks. Works only for static methods.
	[System.AttributeUsage(System.AttributeTargets.Method)]
	public class MonoPInvokeCallbackAttribute : Attribute
	{
		public MonoPInvokeCallbackAttribute (Type type) {}
	}
}

namespace UnityEngine
{

internal class WrapperlessIcall : System.Attribute {
	public WrapperlessIcall () {
	}
}

class AttributeHelperEngine
{
	static Type[] GetRequiredComponents (Type klass)
	{
		// Generate an array for all required components
		// .NET doesnt give us multiple copies of the same attribute on derived classes
		// Thus we do it manually
		List<Type> required = null;
		while (klass != null && klass != typeof (MonoBehaviour))
		{
			object[] attrs = klass.GetCustomAttributes(typeof(RequireComponent), false);
			
			
			for (int i=0;i<attrs.Length;i++)
			{
				RequireComponent attri = (RequireComponent)attrs[i];
				if (required == null && attrs.Length == 1 && klass.BaseType == typeof (MonoBehaviour))
				{
					Type[] types = { attri.m_Type0, attri.m_Type1, attri.m_Type2 };
					return types;
				}
				else
				{
					if (required == null)
						required = new List<Type>();
						
					if (attri.m_Type0 != null)
						required.Add(attri.m_Type0);
					if (attri.m_Type1 != null)
						required.Add(attri.m_Type1);
					if (attri.m_Type2 != null)
						required.Add(attri.m_Type2);
				}
			}
			
			klass = klass.BaseType;
		}
		if (required == null)
			return null;
		else
			return required.ToArray();
	}
			
	static bool CheckIsEditorScript (Type klass)
	{
		while (klass != null && klass != typeof (MonoBehaviour))
		{
			object[] attrs = klass.GetCustomAttributes(typeof(ExecuteInEditMode), false);
			if (attrs.Length != 0)
				return true;
			klass = klass.BaseType;
		}
		return false;
	}
}
}